#include "oled.h"
#include "main.h"
#include "oledfont.h"  	      
#include "math.h"

uint8_t oled_gram[144][8];

//oled的初始化
void oled_Init(void)
{
#if oled_INTERFACE == 1

    // SPI接口
    oled_RES_Clr();
    HAL_Delay(200);
    oled_RES_Set();
#elif  oled_INTERFACE == 2  // I2C接口
    HAL_Delay(200);
#elif  oled_INTERFACE == 3  //模拟spi
    oled_RES_Clr();
    HAL_Delay(200);
    oled_RES_Set();
#else                       //模拟i2c
    HAL_Delay(200);
#endif
    
	oled_write_byte(0xAE,oled_CMD);//--turn off oled panel
	oled_write_byte(0x00,oled_CMD);//---set low column address
	oled_write_byte(0x10,oled_CMD);//---set high column address
	oled_write_byte(0x40,oled_CMD);//--set start line address  Set Mapping RAM display Start Line (0x00~0x3F)
	oled_write_byte(0x81,oled_CMD);//--set contrast control register
	oled_write_byte(0xCF,oled_CMD);// Set SEG Output Current Brightness
	oled_write_byte(0xA1,oled_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
	oled_write_byte(0xC8,oled_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
	oled_write_byte(0xA6,oled_CMD);//--set normal display
	oled_write_byte(0xA8,oled_CMD);//--set multiplex ratio(1 to 64)
	oled_write_byte(0x3f,oled_CMD);//--1/64 duty
	oled_write_byte(0xD3,oled_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
	oled_write_byte(0x00,oled_CMD);//-not offset
	oled_write_byte(0xd5,oled_CMD);//--set display clock divide ratio/oscillator frequency
	oled_write_byte(0x80,oled_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
	oled_write_byte(0xD9,oled_CMD);//--set pre-charge period
	oled_write_byte(0xF1,oled_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
	oled_write_byte(0xDA,oled_CMD);//--set com pins hardware configuration
	oled_write_byte(0x12,oled_CMD);
	oled_write_byte(0xDB,oled_CMD);//--set vcomh
	oled_write_byte(0x40,oled_CMD);//Set VCOM Deselect Level
	oled_write_byte(0x20,oled_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
	oled_write_byte(0x02,oled_CMD);//
	oled_write_byte(0x8D,oled_CMD);//--set Charge Pump enable/disable
	oled_write_byte(0x14,oled_CMD);//--set(0x10) disable
	oled_write_byte(0xA4,oled_CMD);// Disable Entire display On (0xa4/0xa5)
	oled_write_byte(0xA6,oled_CMD);// Disable Inverse display On (0xa6/a7) 
	oled_clear();
	oled_write_byte(0xAF,oled_CMD);
}

void oled_write_byte(uint8_t dat,uint8_t mode)
{	
#if oled_INTERFACE == 1  // SPI接口
    if(mode)
        oled_DC_Set();
    else 
        oled_DC_Clr();
    
    HAL_SPI_Transmit(&oled_spi, &dat, 1, 0X100);
    oled_DC_Set();

#elif  oled_INTERFACE == 2  // I2C接口
    uint8_t buffer[2];
    buffer[0] = mode ? 0x40 : 0x00; // 控制字节
    buffer[1] = dat;                // 数据/命令字节
    HAL_I2C_Master_Transmit(&oled_i2c, oled_I2C_ADDR, buffer, 2, HAL_MAX_DELAY);
		//HAL_I2C_Master_Transmit_DMA(&oled_i2c, oled_I2C_ADDR, buffer, 2);
#elif  oled_INTERFACE == 3  //模拟spi
    uint8_t i;			  
    if(mode)
        oled_DC_Set();
    else 
        oled_DC_Clr();		  
    for(i=0;i<8;i++)
    {			  
        oled_SCL_Clr();
        if(dat&0x80)
            oled_SDA_Set();
        else 
            oled_SDA_Clr();
        oled_SCL_Set();
        dat<<=1;   
    }				 		  
    oled_DC_Set();
#else                       //模拟i2c
    oled_I2C_Start();
    oled_I2C_Send_Byte(0x78);
    oled_I2C_WaitAck();
    if(mode){oled_I2C_Send_Byte(0x40);}
    else{oled_I2C_Send_Byte(0x00);}
    oled_I2C_WaitAck();
    oled_I2C_Send_Byte(dat);
    oled_I2C_WaitAck();
    oled_I2C_Stop();
 #endif  	  
}

#if oled_INTERFACE == 4      //模拟i2c
   //延时
void oled_I2C_Delay(void)
{
	uint8_t t=3;
	while(t--);
}

//起始信号
void oled_I2C_Start(void)
{
	oled_SDA_Set();
	oled_SCL_Set();
	oled_I2C_Delay();
	oled_SDA_Clr();
	oled_I2C_Delay();
	oled_SCL_Clr();
	oled_I2C_Delay();
}

//结束信号
void oled_I2C_Stop(void)
{
	oled_SDA_Clr();
	oled_SCL_Set();
	oled_I2C_Delay();
	oled_SDA_Set();
}

//等待信号响应
void oled_I2C_WaitAck(void) //测数据信号的电平
{
	oled_SDA_Set();
	oled_I2C_Delay();
	oled_SCL_Set();
	oled_I2C_Delay();
	oled_SCL_Clr();
	oled_I2C_Delay();
}

//写入一个字节
void oled_I2C_Send_Byte(uint8_t dat)
{
	uint8_t i;
	for(i=0;i<8;i++)
	{
		if(dat&0x80)//将dat的8位从最高位依次写入
		{
			oled_SDA_Set();
    }
		else
		{
			oled_SDA_Clr();
    }
		oled_I2C_Delay();
		oled_SCL_Set();
		oled_I2C_Delay();
		oled_SCL_Clr();//将时钟信号设置为低电平
		dat<<=1;
  }
}
#endif 



//反显函数
void oled_colorTurn(uint8_t i)
{
	if(i==0)
		{
			oled_write_byte(0xA6,oled_CMD);//正常显示
		}
	if(i==1)
		{
			oled_write_byte(0xA7,oled_CMD);//反色显示
		}
}

//屏幕旋转180度
void oled_displayTurn(uint8_t i)
{
	if(i==0)
		{
			oled_write_byte(0xC8,oled_CMD);//正常显示
			oled_write_byte(0xA1,oled_CMD);
		}
	if(i==1)
		{
			oled_write_byte(0xC0,oled_CMD);//反转显示
			oled_write_byte(0xA0,oled_CMD);
		}
}

//开启oled显示 
void oled_display_On(void)
{
	oled_write_byte(0x8D,oled_CMD);//电荷泵使能
	oled_write_byte(0x14,oled_CMD);//开启电荷泵
	oled_write_byte(0xAF,oled_CMD);//点亮屏幕
}

//关闭oled显示 
void oled_display_Off(void)
{
	oled_write_byte(0x8D,oled_CMD);//电荷泵使能
	oled_write_byte(0x10,oled_CMD);//关闭电荷泵
	oled_write_byte(0xAE,oled_CMD);//关闭屏幕
}

//更新显存到oled	
void oled_refresh(void)
{
	uint8_t i,n;
	for(i=0;i<8;i++)
	{
	   oled_write_byte(0xb0+i,oled_CMD); //设置行起始地址
	   oled_write_byte(0x00,oled_CMD);   //设置低列起始地址
	   oled_write_byte(0x10,oled_CMD);   //设置高列起始地址
	   for(n=0;n<128;n++)
		 oled_write_byte(oled_gram[n][i],oled_DATA);
  }
}
//清屏函数
void oled_clear()
{
	uint8_t i,n;
	for(i=0;i<8;i++)
	{
	   for(n=0;n<128;n++)
			{
			 oled_gram[n][i]=0;//清除所有数据
			}
  }
	oled_refresh();//更新显示
}

//画点 
//x:0~127
//y:0~63
//t:1 填充 0,清空	
void oled_drawPoint(uint8_t x,uint8_t y,uint8_t t)
{
	uint8_t i,m,n;
	i=y/8;
	m=y%8;
	n=1<<m;
	if(t){
		oled_gram[x][i]|=n;
	}
	else
	{
		oled_gram[x][i]=~oled_gram[x][i];
		oled_gram[x][i]|=n;
		oled_gram[x][i]=~oled_gram[x][i];
	}
}

//画线
//x1,y1:起点坐标
//x2,y2:结束坐标
void oled_drawLine(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint8_t mode)
{
	uint16_t t; 
	int xerr=0,yerr=0,delta_x,delta_y,distance;
	int incx,incy,uRow,uCol;
	delta_x=x2-x1; //计算坐标增量 
	delta_y=y2-y1;
	uRow=x1;//画线起点坐标
	uCol=y1;
	if(delta_x>0)incx=1; //设置单步方向 
	else if (delta_x==0)incx=0;//垂直线 
	else {incx=-1;delta_x=-delta_x;}
	if(delta_y>0)incy=1;
	else if (delta_y==0)incy=0;//水平线 
	else {incy=-1;delta_y=-delta_x;}
	if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 
	else distance=delta_y;
	for(t=0;t<distance+1;t++)
	{
		oled_drawPoint(uRow,uCol,mode);//画点
		xerr+=delta_x;
		yerr+=delta_y;
		if(xerr>distance)
		{
			xerr-=distance;
			uRow+=incx;
		}
		if(yerr>distance)
		{
			yerr-=distance;
			uCol+=incy;
		}
	}
}
//x,y:圆心坐标
//r:圆的半径
void oled_drawCircle(uint8_t x,uint8_t y,uint8_t r)
{
	int a, b,num;
    a = 0;
    b = r;
    while(2 * b * b >= r * r)      
    {
        oled_drawPoint(x + a, y - b,1);
        oled_drawPoint(x - a, y - b,1);
        oled_drawPoint(x - a, y + b,1);
        oled_drawPoint(x + a, y + b,1);
 
        oled_drawPoint(x + b, y + a,1);
        oled_drawPoint(x + b, y - a,1);
        oled_drawPoint(x - b, y - a,1);
        oled_drawPoint(x - b, y + a,1);
        
        a++;
        num = (a * a + b * b) - r*r;//计算画的点离圆心的距离
        if(num > 0)
        {
            b--;
            a--;
        }
    }
}



//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//size1:选择字体 6x8/6x12/8x16/12x24
//mode:0,反色显示;1,正常显示
void oled_showChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t size1,uint8_t mode)
{
	//检测不在ASCII范围的字符
#if 0
    if(chr<32||chr>126){
        oled_clear(); 
        oled_showString(0,0,(unsigned char*)"None!",12,1);
        oled_refresh();
        HAL_Delay(1000);
        return;
	}
#else
    if(chr<32||chr>126){    
       chr=' ';        
    }
#endif    
	uint8_t i,m,temp,size2,chr1;
	uint8_t x0=x,y0=y;
	if(size1==8)size2=6;
	else size2=(size1/8+((size1%8)?1:0))*(size1/2);  //得到字体一个字符对应点阵集所占的字节数
	chr1=chr-' ';  //计算偏移后的值
	for(i=0;i<size2;i++)
	{
		if(size1==8)
		{temp=oled_asc2_0806[chr1][i];} //调用0806字体
		else if(size1==12)
        {temp=oled_asc2_1206[chr1][i];} //调用1206字体
		else if(size1==16)
        {temp=oled_asc2_1608[chr1][i];} //调用1608字体
		else if(size1==24)
        {temp=oled_asc2_2412[chr1][i];} //调用2412字体
		else return;
		for(m=0;m<8;m++)
		{
			if(temp&0x01)oled_drawPoint(x,y,mode);
			else oled_drawPoint(x,y,!mode);
			temp>>=1;
			y++;
		}
		x++;
		if((size1!=8)&&((x-x0)==size1/2))
		{x=x0;y0=y0+8;}
		y=y0;
  }
}



//显示字符串
//x,y:起点坐标  
//size1:字体大小 
//*chr:字符串起始地址 
//mode:0,反色显示;1,正常显示
//显示字符串
//x,y:起点坐标  
//size1:字体大小 
//*chr:字符串起始地址 
//mode:0,反色显示;1,正常显示
void oled_showString(uint8_t x,uint8_t y,const uint8_t *p,uint8_t size,uint8_t mode) 
{
    uint8_t x_size=0;    
    if(size==8)
        x_size=6;
	else 
        x_size=size/2;
        
    while(*p!='\0')
    {       
        if(x>(128-x_size)){
            x=0;
            y+=size;
        }
        if(y>(64-size)){
            y=x=0;
            oled_clear();
        }
        oled_showChar(x,y,*p,size,mode);	 
        x+=x_size;
        p++;
    }  
}

//m^n
uint32_t oled_Pow(uint8_t m,uint8_t n)
{
	uint32_t result=1;
	while(n--)
	{
	  result*=m;
	}
	return result;
}

//显示数字
//x,y :起点坐标
//num :要显示的数字
//len :数字的位数
//size:字体大小
//mode:0,反色显示;1,正常显示
void oled_showNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size1,uint8_t mode)
{
	uint8_t t,temp,m=0;
	if(size1==8)m=2;
	for(t=0;t<len;t++)
	{
		temp=(num/oled_Pow(10,len-t-1))%10;
			if(temp==0)
			{
				oled_showChar(x+(size1/2+m)*t,y,'0',size1,mode);
      }
			else 
			{
			  oled_showChar(x+(size1/2+m)*t,y,temp+'0',size1,mode);
			}
  }
}
#if 0

// 新增函数：显示带小数点的字符
void oled_showCharWithDot(uint8_t x, uint8_t y, uint8_t chr, uint8_t size1, uint8_t mode)
{
    // 先显示普通字符
    oled_showChar(x, y, chr, size1, mode);
    
    // 根据字体大小计算小数点位置
    uint8_t dotX = x;
    uint8_t dotY = y;
    
    if(size1 == 8) {
        dotX += 6; // 6x8字体的宽度是6
        dotY += 8; // 小数点放在字符底部
    } 
		else if(size1 == 12) {
        dotX += 6; // 6x12字体的宽度是6
        dotY += 12; // 小数点放在字符底部
    } 
		else if(size1 == 16) {
        dotX += 8; // 8x16字体的宽度是8
        dotY += 16; // 小数点放在字符底部
    } 
		else if(size1 == 24) {
        dotX += 12; // 12x24字体的宽度是12
        dotY += 24; // 小数点放在字符底部
    }
		dotX-=2;
		dotY-=2;
		
    // 绘制小数点
    oled_drawPoint(dotX, dotY, mode);
		
    if(size1 > 16) { // 对于大字体，可以画更大的点
        oled_drawPoint(dotX+1, dotY, mode);
        oled_drawPoint(dotX, dotY+1, mode);
        oled_drawPoint(dotX+1, dotY+1, mode);
    }
}

void oled_showFloat(uint8_t x, uint8_t y, float num, uint8_t integerLen, uint8_t decimalLen, uint8_t size1, uint8_t mode)
{
    uint8_t t, temp;
    uint8_t isOverflow = 0;
    
    // 参数校验
    if(integerLen < 1) integerLen = 1;
    if(decimalLen > 3) decimalLen = 3;
    
    // 处理符号
    uint8_t sign = '+';
    if(num < 0) {
        sign = '-';
        num = -num;
    }
    
    // 计算最大可显示整数值
    uint32_t maxInteger = 1;
    for(t = 0; t < integerLen; t++) maxInteger *= 10;
    maxInteger -= 1;
    
    // 更精确的四舍五入处理
    double roundedNum = (double)num;
    if(decimalLen > 0) {
        double factor = 1.0;
        for(t = 0; t < decimalLen; t++) factor *= 10.0;
        roundedNum = round(num * factor) / factor;
    } else {
        roundedNum = round(num);
    }
    
    // 获取整数部分
    uint32_t integerPart = (uint32_t)roundedNum;
    
    // 检查整数部分是否超界
    if(integerPart > maxInteger) {
        isOverflow = 1;
        integerPart = maxInteger;
        sign = '*';
    }
    
    // 更精确的小数处理
    uint16_t decimalPart = 0;
    if(decimalLen > 0) {
        double decimal = roundedNum - (double)integerPart;
        for(t = 0; t < decimalLen; t++) decimal *= 10.0;
        decimalPart = (uint16_t)round(decimal);
    }
    
    // 显示符号位
    oled_showChar(x, y, sign, size1, 1);
    uint8_t x_offset = size1/2;
    
    // 显示整数部分（除最后一位）
    for(t = 0; t < integerLen - 1; t++) {
        temp = (integerPart / oled_Pow(10, integerLen - 1 - t)) % 10;
        oled_showChar(x + x_offset + (size1/2)*t, y, temp + '0', size1, 1);
    }
    
    // 显示最后一位整数和小数点（如果有小数）
    if(decimalLen > 0) {
        // 获取最后一位整数
        temp = integerPart % 10;
        // 显示带小数点的最后一位数字
        oled_showCharWithDot(x + x_offset + (size1/2)*(integerLen - 1), y, temp + '0', size1, mode);
        
        // 显示小数部分
        for(t = 0; t < decimalLen; t++) {
            temp = (decimalPart / oled_Pow(10, decimalLen - 1 - t)) % 10;
            oled_showChar(x + x_offset + (size1/2)*(integerLen + t), y, temp + '0', size1, 1);
        }
    } else {
        // 没有小数时正常显示最后一位整数
        temp = integerPart % 10;
        oled_showChar(x + x_offset + (size1/2)*(integerLen - 1), y, temp + '0', size1, 1);
    }
}

#else 

void oled_showFloat(uint8_t x, uint8_t y, float num, uint8_t integerLen, uint8_t decimalLen, uint8_t size1, uint8_t mode)
{
    uint8_t t, temp;
    
    // 参数校验
    if(integerLen < 1) integerLen = 1;
    if(decimalLen > 3) decimalLen = 3;
    
    // 处理符号
    uint8_t sign = '+';
    if(num < 0) {
        sign = '-';
        num = -num;
    }
    
    // 计算最大可显示整数值
    uint32_t maxInteger = 1;
    for(t = 0; t < integerLen; t++) maxInteger *= 10;
    maxInteger -= 1;
    
    // 更精确的四舍五入处理
    double roundedNum = (double)num;
    if(decimalLen > 0) {
        double factor = 1.0;
        for(t = 0; t < decimalLen; t++) factor *= 10.0;
        roundedNum = round(num * factor) / factor;
    } else {
        roundedNum = round(num);
    }
    
    // 获取整数部分
    uint32_t integerPart = (uint32_t)roundedNum;
    
    // 检查整数部分是否超界
    if(integerPart > maxInteger) {
        integerPart = maxInteger;
        sign = '*';
    }
    
    // 更精确的小数处理
    uint16_t decimalPart = 0;
    if(decimalLen > 0) {
        double decimal = roundedNum - (double)integerPart;
        for(t = 0; t < decimalLen; t++) decimal *= 10.0;
        decimalPart = (uint16_t)round(decimal);
    }
    
    // 显示符号位
    oled_showChar(x, y, sign, size1, 1);
		
    uint8_t x_offset = size1/2;
    if(size1==8)
			x_offset+=2;
		
		
    // 显示整数部分
    for(t = 0; t < integerLen; t++) {
        temp = (integerPart / oled_Pow(10, integerLen - 1 - t)) % 10;
        oled_showChar(x + x_offset + (x_offset)*t, y, temp + '0', size1, 1);
    }
    
    // 显示小数部分
    if(decimalLen > 0) {
        oled_showChar(x + x_offset + (x_offset)*integerLen, y, '.', size1, 1);
        
        for(t = 0; t < decimalLen; t++) {
            temp = (decimalPart / oled_Pow(10, decimalLen - 1 - t)) % 10;
            oled_showChar(x + x_offset + (x_offset)*(integerLen + 1 + t), y, temp + '0', size1, 1);
        }
    }
}

#endif
void oled_debug_interrupt(const uint8_t *p, float x)
{
    oled_clear();
    oled_showString(0,0,(unsigned char*)"printf:",16,1);
    oled_showFloat(0,16,x,8,1,16,0);
    oled_refresh();
    oled_showString(0,48,(unsigned char*)">press",16,1);
    oled_showString(0,32,(unsigned char*)p,16,1);
    
    oled_refresh();
    /*while(1) { 
        if(HAL_GPIO_ReadPin(KEY_USER_GPIO_Port,KEY_USER_Pin)==GPIO_PIN_RESET) {
            HAL_Delay(100);
            if(HAL_GPIO_ReadPin(KEY_USER_GPIO_Port,KEY_USER_Pin)==GPIO_PIN_RESET) {
                break;
            }
        }
    }*/
}

//x,y：起点坐标
//sizex,sizey,图片长宽
//BMP[]：要写入的图片数组
//mode:0,反色显示;1,正常显示
void oled_showPicture(uint8_t x,uint8_t y,uint8_t sizex,uint8_t sizey,uint8_t BMP[],uint8_t mode)
{
	uint16_t j=0;
	uint8_t i,n,temp,m;
	uint8_t x0=x,y0=y;
	sizey=sizey/8+((sizey%8)?1:0);
	for(n=0;n<sizey;n++)
	{
		 for(i=0;i<sizex;i++)
		 {
				temp=BMP[j];
				j++;
				for(m=0;m<8;m++)
				{
					if(temp&0x01)oled_drawPoint(x,y,mode);
					else oled_drawPoint(x,y,!mode);
					temp>>=1;
					y++;
				}
				x++;
				if((x-x0)==sizex)
				{
					x=x0;
					y0=y0+8;
				}
				y=y0;
     }
	 }
}

void oled_Test(void){
    for(int i=0;i<128;i++){
        for(int j=0;j<64;j++){
            oled_drawPoint(i,j,1);
            //oled_refresh();                          
        }
        oled_refresh();    
    }
    HAL_Delay(500);
    oled_clear();
    HAL_Delay(500);
}

void fps(void){
    int time=HAL_GetTick(),count=0;
    while (1){
        oled_showString(0,0,(unsigned char*)"fps",12,1);
        oled_showString(0,24,(unsigned char*)"asasasdadadad!@12*&%^&*%@%^&*((saydgahgsd35a464aasadsaddasaddk",12,1);
        if(HAL_GetTick()-time>=1000){
            oled_showNum(128-6*3,0,count,3,12,1);
            //LCD_showNum(LCD_W-3*xsize,1*ysize,count,3,ysize,0,RED,WHITE);
            oled_refresh();
            count=0;
            time=HAL_GetTick();
        }
        oled_refresh();
        //oled_clear();
        count++; 
    }
}
/**
  * @brief  在oled上显示二进制数
  * @param  x,y: 起始坐标
  * @param  num: 要显示的数字
  * @param  len: 显示位数（自动补零）
  * @param  size1: 字体大小
  * @param  mode: 0-反色显示 1-正常显示
  * @retval 无
  */
void oled_showBin(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size1, uint8_t mode)
{
    uint8_t temp;
    uint8_t x_offset = size1/2;
    if(size1 == 8) x_offset += 2;
    
    // 从高位到低位逐位显示
    for(uint8_t t=0; t<len; t++) {
        temp = (num >> (len-1-t)) & 0x01; // 获取第t位
        oled_showChar(x + x_offset*t, y, temp + '0', size1, mode);
    }
}

/**
  * @brief  在oled上显示十六进制数
  * @param  x,y: 起始坐标
  * @param  num: 要显示的数字
  * @param  len: 显示位数（自动补零）
  * @param  size1: 字体大小
  * @param  mode: 0-反色显示 1-正常显示
  * @retval 无
  */
void oled_showHex(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size1, uint8_t mode)
{
    uint8_t temp;
    uint8_t x_offset = size1/2;
    if(size1 == 8) x_offset += 2;
    
    // 从高位到低位逐位显示
    for(uint8_t t=0; t<len; t++) {
        temp = (num >> ((len-1-t)*4)) & 0x0F; // 获取第t个十六进制位
        
        // 转换为ASCII字符
        if(temp < 10) temp += '0';
        else temp += ('A'-10);
        
        oled_showChar(x + x_offset*t, y, temp, size1, mode);
    }
}

// 带前缀的十六进制显示（如"0x1234"）
void oled_showHexWithPrefix(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size1, uint8_t mode)
{
    // 显示"0x"前缀
    uint8_t x_size=size1/2;
    if(size1==8)
        x_size=6;
    
    oled_showChar(x, y, '0', size1, mode);
    oled_showChar(x + x_size, y, 'x', size1, mode);
    
    // 显示数值部分
    oled_showHex(x + x_size*2, y, num, len, size1, mode);
}

// 带前缀的二进制显示（如"b1010"）
void oled_showBinWithPrefix(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size1, uint8_t mode)
{
    // 显示"b"前缀
    oled_showChar(x, y, 'b', size1, mode);
    
    uint8_t x_size=size1/2;
    if(size1==8)
        x_size=6;
    
    // 显示数值部分
    oled_showBin(x + x_size, y, num, len, size1, mode);
}

void oled_showChinese(uint8_t x,uint8_t y,uint8_t num)
{
	uint8_t m,temp;
	uint8_t x0=x,y0=y,size1=16;
	uint16_t i,size3=(size1/8+((size1%8)?1:0))*size1;  
	for(i=0;i<size3;i++)
	{
		temp=Hzk1[num][i];
		for(m=0;m<8;m++)
		{
			if(temp&0x01)oled_drawPoint(x,y,1);
			else oled_drawPoint(x,y,!1);
			temp>>=1;
			y++;
		}
		x++;
		if((x-x0)==size1)
		{x=x0;y0=y0+8;}
		y=y0;
	}
}
//例程里的,无法处理3个汉字的情况
void oled_Scrolldisplay(uint8_t num,uint8_t space)
{
	uint8_t i,n,t=0,m=0,r;
	while(1)
	{
		if(m==0)
		{
	    oled_showChinese(128,24,t); 
			t++;
		}
		if(t==num)
			{
				for(r=0;r<16*space;r++)     
				 {
					for(i=1;i<144;i++)
						{
							for(n=0;n<8;n++)
							{
								oled_gram[i-1][n]=oled_gram[i][n];
							}
						}
           oled_refresh();
				 }
        t=0;
      }
		m++;
		if(m==16){m=0;}
		for(i=1;i<144;i++)   
		{
			for(n=0;n<8;n++)
			{
				oled_gram[i-1][n]=oled_gram[i][n];
			}
		}
		oled_refresh();
	}
}

//重新实现滚动
//屏幕是128x64, 汉字是16x16,滚动区域的高度为16像素(2个page)
/*我的思路是基于缓冲区的,
我目前的oled显示前都会把要显示的点阵放到一个数组里,
修改完了后再调用oled_refrush把这个数组传到oled刷新显示.
那我就可以对一个区域(0,0)~(163,16)进行堆栈式挪动,把最左的一列(0,0)~(0,16)移动到缓冲向量里,
然后把第二列搬到第一列,以此类推,搬完最后一列时,
把缓存区里的数据填到最后一列里,就完成了一次滚动,
然后我调用oled_refrush并加一个delay,进行下一次滚动,一直循环
*/

void oled_show_name_rolling(void){
	uint8_t oled_temp[128][64];
	oled_showChinese(0,0,0);
	oled_showChinese(16,0,1);
	oled_showChinese(32,0,2);
	uint8_t temp[16],i=0,j=0;
	//第一列存入缓冲区
	for (i=0;i<16;i++){
		temp[i]=oled_temp[0][i];
	}
	//将下一列搬到上一列
	for (i=0;i<15;i++){
		for (j=0;j<16;j++)
		oled_temp[i][j]=oled_temp[i+1][j];
	}
	//从缓冲向量搬到最后一列
	for (i=0;i<16;i++){
		oled_temp[15][i]=temp[i];
	}
}

// 基于页模式的滚动函数
void oled_show_name_rolling_adapted(void)
{
    // --- 初始化：在显存中画好初始内容 ---
    // 在缓冲区的 (0,0), (16,0), (32,0) 位置画上三个汉字
    // 注意：这里的y=0，对应的是Page 0
    oled_showChinese(0, 0, 0);  // 在 GRAM 的 [0..15][0..1] 区域写入数据
    oled_showChinese(16, 0, 1); // 在 GRAM 的 [16..31][0..1] 区域写入数据
    oled_showChinese(32, 0, 2); // 在 GRAM 的 [32..47][0..1] 区域写入数据
    
    // 刷新一次，显示初始状态
    oled_refresh();
    //HAL_Delay(1000); // 等待1秒

    // --- 滚动循环 ---
    while(1)
    {
        // 1. 定义一个临时缓冲区，用于保存最左侧一列的数据
        // 因为滚动区域的高度是16像素，跨越2个页，所以缓冲区大小是2
        uint8_t temp_col_buffer[2]; 
        
        // 2. 把第0列的数据（跨越2个页）存入临时缓冲区
        temp_col_buffer[0] = oled_gram[0][0]; // 保存Page 0的数据
        temp_col_buffer[1] = oled_gram[0][1]; // 保存Page 1的数据

        // 3. 将后续列的数据（1到47列）依次向左搬移一格
        // 遍历所有需要移动的列
        for (uint8_t col = 0; col < 47; col++) 
        {
            // 遍历滚动区域涉及的所有页 (这里是Page 0和Page 1)
            for (uint8_t page = 0; page < 2; page++)
            {
                oled_gram[col][page] = oled_gram[col + 1][page];
            }
        }

        // 4. 把临时缓冲区的数据（即原始的第0列）填到最后一列（第47列）
        oled_gram[47][0] = temp_col_buffer[0];
        oled_gram[47][1] = temp_col_buffer[1];

        // 5. 刷新整个屏幕以显示滚动效果
        oled_refresh();

        // 6. 加一点延时来控制滚动速度
        HAL_Delay(50); // 延时50ms，可以调整
    }
}



